#pragma once

#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

// 这个类也可以解mysql resultset协议结果集, 但仅限解到Column Def, 后面的Value Def是不解的
class MySQLResultSetParser {
  public:
    enum class ParseStatus {
        COMPLETE,   // 解析成功完成
        INCOMPLETE, // 数据不完整但非错误
        TRUNCATED,  // 数据被截断
        MALFORMED   // 数据格式错误
    };

    struct ColumnInfo {
        std::string name;
        std::string type;
    };

    // 解析MySQL结果集数据包
    ParseStatus parse(const std::vector<uint8_t> &packet) {
        if (packet.empty()) {
            return ParseStatus::MALFORMED;
        }

        size_t pos = 0;
        auto status = parse_result_set(packet, pos);

        // 检查剩余数据
        if (status == ParseStatus::COMPLETE && pos != packet.size()) {
            std::cerr << "Warning: " << (packet.size() - pos) << " bytes remaining at end of packet" << std::endl;
            dump_hex(packet, pos);
        }

        return status;
    }

    // 获取解析结果
    uint8_t getPacketNumber() const { return packet_number; }
    const std::string &getSchema() const { return schema; }
    const std::string &getTable() const { return table; }
    size_t getColumnCount() const { return column_count; }
    const std::vector<ColumnInfo> &getColumns() const { return columns; }

  private:
    uint8_t packet_number = 0;
    std::string schema;
    std::string table;
    size_t column_count = 0;
    std::vector<ColumnInfo> columns;

    // 解析结果集主逻辑
    ParseStatus parse_result_set(const std::vector<uint8_t> &packet, size_t &pos) {
        // 1. 解析包头
        ParseStatus status = parse_header(packet, pos);
        if (status != ParseStatus::COMPLETE) {
            return status;
        }

        // 2. 解析列数量
        status = parse_column_count(packet, pos, column_count);
        if (status != ParseStatus::COMPLETE) {
            return status;
        }

        // 3. 解析列定义
        for (size_t i = 0; i < column_count; ++i) {
            status = parse_column_definition(packet, pos, i == 0);
            if (status != ParseStatus::COMPLETE) {
                // 首列解析失败视为错误，其他列可能是正常结束
                return i == 0 ? status : ParseStatus::INCOMPLETE;
            }
        }

        return ParseStatus::COMPLETE;
    }

    // 解析包头
    ParseStatus parse_header(const std::vector<uint8_t> &packet, size_t &pos) {
        if (pos + 4 > packet.size()) {
            return ParseStatus::TRUNCATED;
        }

        packet_number = packet[pos + 3]; // 第4字节是packet number
        pos += 4;
        return ParseStatus::COMPLETE;
    }

    // 解析列数量
    ParseStatus parse_column_count(const std::vector<uint8_t> &packet, size_t &pos, uint64_t &count) {
        if (pos >= packet.size()) {
            return ParseStatus::TRUNCATED;
        }
        count = static_cast<uint64_t>(packet[pos]);
        pos += 1; // count字段只有1字节
        return ParseStatus::COMPLETE;
    }

    // 解析列定义
    ParseStatus parse_column_definition(const std::vector<uint8_t> &packet, size_t &pos, bool first_column) {
        // 1. 检查包头是否完整 (4字节)
        if (pos + 4 > packet.size()) {
            return ParseStatus::TRUNCATED;
        }

        // 2. 解析包头 (3字节长度 + 1字节序号)
        uint32_t packet_length = packet[pos] | (packet[pos + 1] << 8) | (packet[pos + 2] << 16);
        uint8_t packet_num = packet[pos + 3];
        pos += 4;

        // 3. 解析目录 ("def")
        if (pos + 1 > packet.size())
            return ParseStatus::TRUNCATED;
        uint8_t catalog_len = packet[pos++];
        if (pos + catalog_len > packet.size())
            return ParseStatus::TRUNCATED;
        pos += catalog_len; // 跳过catalog内容

        // 4. 解析数据库名
        if (pos + 1 > packet.size())
            return ParseStatus::TRUNCATED;
        uint8_t db_len = packet[pos++];
        if (pos + db_len > packet.size())
            return ParseStatus::TRUNCATED;
        if (first_column) {
            schema.assign(reinterpret_cast<const char *>(&packet[pos]), db_len);
        }
        pos += db_len;

        // 5. 解析表名
        if (pos + 1 > packet.size())
            return ParseStatus::TRUNCATED;
        uint8_t table_len = packet[pos++];
        if (pos + table_len > packet.size())
            return ParseStatus::TRUNCATED;
        if (first_column) {
            table.assign(reinterpret_cast<const char *>(&packet[pos]), table_len);
        }
        pos += table_len;

        // 6. 解析原始表名
        if (pos + 1 > packet.size())
            return ParseStatus::TRUNCATED;
        uint8_t org_table_len = packet[pos++];
        if (pos + org_table_len > packet.size())
            return ParseStatus::TRUNCATED;
        pos += org_table_len;

        // 7. 解析列名
        if (pos + 1 > packet.size())
            return ParseStatus::TRUNCATED;
        uint8_t col_name_len = packet[pos++];
        if (pos + col_name_len > packet.size())
            return ParseStatus::TRUNCATED;
        std::string column_name(reinterpret_cast<const char *>(&packet[pos]), col_name_len);
        pos += col_name_len;

        // 8. 解析原始列名
        if (pos + 1 > packet.size())
            return ParseStatus::TRUNCATED;
        uint8_t org_col_name_len = packet[pos++];
        if (pos + org_col_name_len > packet.size())
            return ParseStatus::TRUNCATED;
        pos += org_col_name_len;

        // 9. 解析固定长度部分 (共16字节)
        if (pos + 16 > packet.size()) {
            return ParseStatus::TRUNCATED;
        }

        // 9.1 跳过0x0C (1字节)
        pos += 1;

        // 9.2 字符集 (2字节)
        uint16_t charset = packet[pos] | (packet[pos + 1] << 8);
        pos += 2;

        // 9.3 列长度 (4字节)
        uint32_t column_length = packet[pos] | (packet[pos + 1] << 8) | (packet[pos + 2] << 16) | (packet[pos + 3] << 24);
        pos += 4;

        // 9.4 列类型 (1字节)
        uint8_t column_type = packet[pos++];

        // 9.5 标志位 (2字节)
        uint16_t flags = packet[pos] | (packet[pos + 1] << 8);
        pos += 2;

        // 9.6 小数位数 (1字节)
        uint8_t decimals = packet[pos++];

        // 9.7 填充 (2字节)
        pos += 2;

        // 存储列信息
        columns.push_back({column_name, mysql_type_to_string(column_type)});

        return ParseStatus::COMPLETE;
    }

    // MySQL类型转换为字符串
    std::string mysql_type_to_string(uint8_t type) {
        switch (type) {
        case 0x00:
            return "DECIMAL";
        case 0x01:
            return "TINY";
        case 0x02:
            return "SHORT";
        case 0x03:
            return "LONG";
        case 0x04:
            return "FLOAT";
        case 0x05:
            return "DOUBLE";
        case 0x06:
            return "NULL";
        case 0x07:
            return "TIMESTAMP";
        case 0x08:
            return "LONGLONG";
        case 0x09:
            return "INT24";
        case 0x0a:
            return "DATE";
        case 0x0b:
            return "TIME";
        case 0x0c:
            return "DATETIME";
        case 0x0d:
            return "YEAR";
        case 0x0e:
            return "NEWDATE";
        case 0x0f:
            return "VARCHAR";
        case 0x10:
            return "BIT";
        case 0xf5:
            return "JSON";
        case 0xf6:
            return "NEWDECIMAL";
        case 0xf7:
            return "ENUM";
        case 0xf8:
            return "SET";
        case 0xf9:
            return "TINY_BLOB";
        case 0xfa:
            return "MEDIUM_BLOB";
        case 0xfb:
            return "LONG_BLOB";
        case 0xfc:
            return "BLOB";
        case 0xfd:
            return "VAR_STRING";
        case 0xfe:
            return "STRING";
        case 0xff:
            return "GEOMETRY";
        default:
            return "UNKNOWN";
        }
    }

    // 十六进制dump工具函数
    void dump_hex(const std::vector<uint8_t> &data, size_t start_pos) {
        for (size_t i = start_pos; i < data.size(); ++i) {
            std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[i]) << " ";
            if ((i - start_pos) % 16 == 15)
                std::cout << std::endl;
        }
        std::cout << std::dec << std::endl;
    }
};